﻿using System;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.ComponentModel;
using SedionFormDesigner.Designer;
using System.ComponentModel.Design.Serialization;

namespace SedionFormDesigner.Service
{
    /// <summary>
    ///  实现设计器序列化管理,用来创建对象,查找类型,标志对象以及自定义特定类型的序列化
    /// </summary>
    internal class SedionDesignerSerializationManager : IDesignerSerializationManager
    {
        private SedionDesignerLoader loader;
        private ResolveNameEventHandler resolveNameEventHandler;
        private EventHandler serializationCompleteEventHandler;
        private PropertyDescriptorCollection propertyCollection;

        // 保存实例化与名称的键值对
        private Hashtable instancesByName;
        private Hashtable namesByInstance;
        // 串行器键值对集合
        private Hashtable serializers;
        // 保存错误的集合
        private ArrayList errorList;
        // 提供堆栈程序,序列化程序可使用该对象向嵌套的序列化程序提供信息
        private ContextStack contextStack;
        // 访问接口的集合
        private ArrayList designerSerializationProviders;

        internal SedionDesignerSerializationManager(SedionDesignerLoader loader)
        {
            this.loader = loader;
        }

        #region IDesignerSerializationManager 成员

        public void AddSerializationProvider(IDesignerSerializationProvider provider)
        {
            if (designerSerializationProviders == null)
                designerSerializationProviders = new ArrayList();
            designerSerializationProviders.Add(provider);
        }

        public void RemoveSerializationProvider(IDesignerSerializationProvider provider)
        {
            if (designerSerializationProviders != null)
                designerSerializationProviders.Remove(provider);
        }

        /// <summary>
        ///  用来提供一个用户定义的存储空间
        /// </summary>
        public ContextStack Context
        {
            get
            {
                if (contextStack == null)
                    contextStack = new ContextStack();
                return contextStack;
            }
        }

        /// <summary>
        ///  创建指定对象实例并相应的保存到Hashtable中
        /// </summary>
        public object CreateInstance(Type type, System.Collections.ICollection arguments, string name, bool addToContainer)
        {
            Object[] argArray = null;
            if (arguments != null && arguments.Count > 0)
            {
                arguments = new Object[arguments.Count];
                arguments.CopyTo(argArray, 0);
            }

            Object instance = null;

            // 如果需要将实例添加到容器中,且类型为IComponent
            // 则直接访问host防止第二次添加实例时,由于名称同,造成重命名的开销
            if (addToContainer && typeof(IComponent).IsAssignableFrom(type))
            {
                IDesignerLoaderHost host = loader.LoaderHost;
                if (host != null)
                {
                    if (name == null)
                        instance = host.CreateComponent(type);
                    else
                        instance = host.CreateComponent(type, name);
                }
            }

            if (instance == null)
            {
                if (name != null && instancesByName != null)
                {
                    if (instancesByName.ContainsKey(name))
                        throw new InvalidOperationException(String.Concat("已经存在名为: ", name, "的实例"));
                }

                try
                {
                    // 创建指定类型的实例
                    instance = Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance,
                        null, argArray, null);
                }
                // 视图动态访问不存在的方法
                catch (MissingMethodException)
                {
                    StringBuilder argTypes = new StringBuilder();
                    foreach (Object o in argArray)
                    {
                        if (argArray.Length > 0)
                            argTypes.Append(", ");

                        if (o != null)
                            argTypes.Append(o.GetType().Name);
                        else
                            argTypes.Append("null");
                    }

                    throw new InvalidOperationException(String.Concat("无法找到指定类的构造函数: ", type.FullName, " (", argTypes.ToString(), ")"));
                }
                // 如果有名称但是添加到design container的对象不是component
                // 那么用自己的Hashtable来记录键值对
                if (name != null)
                {
                    if (instancesByName == null)
                    {
                        instancesByName = new Hashtable();
                        namesByInstance = new Hashtable();
                    }
                    instancesByName[name] = instance;
                    namesByInstance[instance] = name;
                }
            }

            return instance;
        }

        /// <summary>
        ///  根据名字获得实例
        ///  如果不存在则返回null
        /// </summary>
        public object GetInstance(string name)
        {
            Object instance = null;
            if (name == null)
                throw new ArgumentNullException("name");

            if (instancesByName != null)
                instance = instancesByName[name];

            // 如果保存的键值对中不存在实例
            // 则在host的组件集合中获取实例
            if (instance == null && loader.LoaderHost != null)
            {
                instance = loader.LoaderHost.Container.Components[name];
            }

            if (instance == null && resolveNameEventHandler != null)
            {
                // 序列化进程时,将一个名称与一个对象实例相匹配
                ResolveNameEventArgs e = new ResolveNameEventArgs(name);
                resolveNameEventHandler(this, e);
                instance = e.Value;
            }

            return instance;
        }

        /// <summary>
        ///  根据实例获得对应的名称,或者为null,
        ///  如果实例没有名称
        /// </summary>
        public string GetName(object value)
        {
            String name = null;
            if (value == null)
                throw new ArgumentNullException("value");

            if (namesByInstance != null)
                name = (String)namesByInstance[value];

            // 如果存储的键值对不存在且对象实现IComponent接口
            // 那么获得组件对应的名称
            if (name == null && value is IComponent)
            {
                ISite site = ((IComponent)value).Site;
                if (site != null)
                    name = site.Name;
            }

            return name;
        }

        /// <summary>
        ///  获得给予对象的要求的串行器(serializer)
        /// </summary>
        public object GetSerializer(Type objectType, Type serializerType)
        {
            Object serializer = null;

            if (objectType != null)
            {
                if (serializer != null)
                {
                    serializer = serializers[objectType];
                    if (serializer != null && !serializerType.IsAssignableFrom(serializer.GetType()))
                        serializer = null;
                }

                IDesignerLoaderHost host = loader.LoaderHost;
                if (serializer == null && host != null)
                {
                    // 在指定类型集合中返回特性集合
                    AttributeCollection attributes = TypeDescriptor.GetAttributes(objectType);
                    foreach (Attribute attr in attributes)
                    {
                        if (attr is DesignerSerializerAttribute)
                        {
                            DesignerSerializerAttribute dsAttr = (DesignerSerializerAttribute)attr;
                            String typeName = dsAttr.SerializerBaseTypeName;

                            // 遍历,获得匹配的对象,并创建serializer实例
                            if (typeName != null && host.GetType(typeName) == serializerType &&
                                dsAttr.SerializerTypeName != null && dsAttr.SerializerBaseTypeName.Length > 0)
                            {
                                Type type = host.GetType(dsAttr.SerializerTypeName);
                                Debug.Assert(type != null, String.Concat("Type ", objectType.FullName,
                                    " has a serializer that we couldn't bind to: ", dsAttr.SerializerTypeName));

                                if (type != null)
                                {
                                    serializer = Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
                                        | BindingFlags.CreateInstance, null, null, null);
                                    break;
                                }
                            }
                        }
                    }

                    if (serializer != null)
                    {
                        if (serializers == null)
                            serializers = new Hashtable();
                        serializers[objectType] = serializer;
                    }
                }
            }

            if (designerSerializationProviders != null)
            {
                Boolean continueLoop = true;
                for (int i = 0; continueLoop && i < designerSerializationProviders.Count; i++)
                {
                    continueLoop = false;
                    foreach (IDesignerSerializationProvider provider in designerSerializationProviders)
                    {
                        Object newSerializer = provider.GetSerializer(this, serializer, objectType, serializerType);
                        if (newSerializer != null)
                        {
                            continueLoop = (serializer != newSerializer);
                            serializer = newSerializer;
                        }
                    }
                }
            }

            return serializer;
        }

        /// <summary>
        ///  给定名称获得类型
        /// </summary>
        public Type GetType(string typeName)
        {
            Type type = null;

            if (loader.LoaderHost != null)
            {
                while (type == null)
                {
                    type = loader.LoaderHost.GetType(typeName);

                    if (type == null && typeName != null && typeName.Length > 0)
                    {
                        Int32 dotIndex = typeName.LastIndexOf('.');
                        if (dotIndex == -1 || dotIndex == typeName.Length - 1)
                            break;

                        typeName = String.Concat(typeName.Substring(0, dotIndex), "+", typeName.Substring(dotIndex + 1, typeName.Length - dotIndex - 1));
                    }
                }
            }
            return type;
        }

        /// <summary>
        ///  获得属性集合
        /// </summary>
        public System.ComponentModel.PropertyDescriptorCollection Properties
        {
            get
            {
                if (propertyCollection == null)
                    propertyCollection = new PropertyDescriptorCollection(new PropertyDescriptor[] { });
                return propertyCollection;
            }
        }

        /// <summary>
        ///  保存错误,再一次性汇报
        ///  或者遇到则直接抛出,Serialization可能再继续执行
        /// </summary>
        public void ReportError(object errorInformation)
        {
            if (errorInformation != null)
            {
                if (errorList == null)
                    errorList = new ArrayList();
                errorList.Add(errorInformation);
            }
        }

        // 解析名称
        public event ResolveNameEventHandler ResolveName
        {
            add
            {
                resolveNameEventHandler += value;
            }
            remove
            {
                resolveNameEventHandler -= value;
            }
        }

        // 完成序列化
        public event EventHandler SerializationComplete
        {
            add
            {
                serializationCompleteEventHandler += value;
            }
            remove
            {
                serializationCompleteEventHandler -= value;
            }
        }

        /// <summary>
        ///  给实例命名
        /// </summary>
        public void SetName(object instance, string name)
        {
            if (instance == null)
                throw new ArgumentNullException("instance");

            if (name == null)
                throw new ArgumentNullException("name");

            if (instancesByName == null)
            {
                instancesByName = new Hashtable();
                namesByInstance = new Hashtable();
            }

            if (instancesByName[name] != null)
                throw new ArgumentException(String.Concat(name, " 已经被使用"));

            if (namesByInstance[instance] != null)
                throw new ArgumentException(String.Concat("载入的对象中已经有名为 ", name, "."));

            instancesByName[name] = instance;
            namesByInstance[instance] = name;
        }

        #endregion

        #region IServiceProvider 成员

        public object GetService(Type serviceType)
        {
            return loader.GetService(serviceType);
        }

        #endregion
    }
}
